<?php
/**
 * Pertyler DatabaseManagement
 * DatabaseModel
 * Row Classes
 *
 * @author	Emre Hasegeli <hasegeli@gmail.com>
 * @license	GNU General Public License v3
 */

namespace Pertyler;

require_once __DIR__ . '/main.php';

require_once __DIR__ . '/aRow.php';

class PublishedRow extends Table_Row
{
	public function SelectTableArray()
	{
		return $this->table->SelectRowsTableArray($this);
	}

	public function SelectTable($id)
	{
		$table = Table::Select($id);

		if($table)
			return $table->RowsTable($this);

		throw new Database_exception('Table cannot found.');
	}

	public function SelectGroupArray(Row_GroupColumnValue $groupColumnValue)
	{
		return $this->table->SelectRowsGroupPublishedRowArray($this,
				$groupColumnValue);
	}

	public function UpdateAsJoinedIntoGroup(Row_GroupColumnValue $groupColumnValue,
			self $row)
	{
		$privilege = $this->table->SelectPrivilege('update');

		if(!$privilege)
			throw new Database_exception('No ' . $privilage . ' privilege');

		require_once __DIR__ . '/Role.php';

		if(!Role::Select()->SelectRolePrivilege($privilege))
			throw new RolePrivilege_exception($privilege);

		$rowGroupColumnValueArray = $row->SelectGroupColumnValueArray();

		$rowGroupColumnValue = $rowGroupColumnValueArray[$groupColumnValue->Column()->Priority()];

		Database::Get()->UpdateTransactionBegin();

		if($groupColumnValue->Value())
			$this->UpdateAsRemovedFromGroup($groupColumnValue);

		try
		{
			if($rowGroupColumnValue->Value())
				Database::Get()->SelectResultArray('
UPDATE "' . $this->table->Schema() . '"."' . $this->table->BackgroundName() . '"
	SET "' . $rowGroupColumnValue->Column()->BackgroundName() . '" = ' . $rowGroupColumnValue->Value() . '
	WHERE id = \'' . $this->Id() . '\'');
			else
			{
				$group = Database::Get()->SelectResult('SELECT nextval(\'"' . $this->table->Schema() . '"."' . $this->table->UniqueName() . '_' . $column->BackgroundName() . '"\'::regclass)');

				Database::Get()->Update('
UPDATE "' . $this->table->Schema() . '"."' . $this->table->BackgroundName() . '"
	SET "' . $column->BackgroundName() . '" = ' . $group . '
	WHERE id IN (\'' . $this->Id() . '\', \'' . $row->Id() . '\')');
			}
		}
		catch(Database_exception $e)
		{
			Database::Get()->UpdateTransactionRollback();

			throw new Database_exception('Wrong SQL for update table "' . $this->table->UniqueName() . '"');
		}

		Role_Moderator::Select()->InsertChangeLog($privilege,
				$this->Id());

		Database::Get()->UpdateTransactionCommit();

		return true;
	}

	public function UpdateAsRemovedFromGroup(Row_GroupColumnValue $groupColumnValue)
	{
		if(!($privilege = $this->table->SelectPrivilege('update')))
			throw new Database_exception('No ' . $privilage . ' privilege');

		if(!Role::Select()->SelectRolePrivilege($privilege))
			throw new RolePrivilege_exception($privilege);

		if(!$groupColumnValue->Value())
			return false;

		Database::Get()->UpdateTransactionBegin();

		try
		{
			if(count($this->SelectGroupArray($groupColumnValue)) <= 2)
				Database::Get()->SelectResultArray('
UPDATE "' . $this->table->Schema() . '"."' . $this->table->BackgroundName() . '"
	SET "' . $groupColumnValue->Column()->BackgroundName() . '" = NULL
	WHERE "' . $groupColumnValue->Column()->BackgroundName() . '" = \'' . $groupColumnValue->Value() . '\'');
			else
				Database::Get()->Update('
UPDATE "' . $this->table->Schema() . '"."' . $this->table->BackgroundName() . '"
	SET "' . $groupColumnValue->Column()->BackgroundName() . '" = NULL
	WHERE id = \'' . $this->Id() . '\'');
		}
		catch(Database_exception $e)
		{
			Database::Get()->UpdateTransactionRollback();

			throw new Database_exception('Wrong SQL for update table "' . $this->table->UniqueName() . '"');
		}

		Role_Moderator::Select()->InsertChangeLog($privilege,
				$this->Id());

		Database::Get()->UpdateTransactionCommit();

		return true;
	}
}

class PublishedRow_Table extends Table
{
	private $parent;

	protected function __construct(PublishedRow $parent,
			$parent_id,
			$id,
			$name,
			$shortName,
			$backgroundName,
			$schema,
			$hasNameTable,
			$hasNameTableAlternativeColumn,
			$hasLanguage,
			$tableType,
			$hasUnpublishedColumn)
	{
		$this->parent = $parent;

		parent::__construct($parent_id,
				$id,
				$name,
				$shortName,
				$backgroundName,
				$schema,
				$hasNameTable,
				$hasNameTableAlternativeColumn,
				$hasLanguage,
				$tableType,
				$hasUnpublishedColumn);
	}

	public function __ToString()
	{
		if($this->shortName)
			return $this->shortName;

		return parent::__ToString();
	}

	public function SelectPublishedRowArray()
	{
		if(!($privilege = $this->SelectPrivilege('select')))
			throw new Exception('No privilege for table ' . $this->Id());

		if(!Role::Select()->SelectRolePrivilege($privilege))
			throw new RolePrivilege_exception($privilege);

		$sQLGeneratorTable = $this->withParentPublishedPostgreSQLGeneratorTable();

		require_once __DIR__ . '/../library/Pert/PostgreSQLGenerator/Condition.php';

		require_once __DIR__ . '/../library/Pert/PostgreSQLGenerator/Input.php';

		$sQLGeneratorTable->AddCondition(new \Pert\PostgreSQLGenerator\Condition($this->SelectParentTable()->UniqueName(),
				new \Pert\PostgreSQLGenerator\Input($this->parent->Id())));

		try
		{
			$resultArrayArray = Database::Get()->SelectResultArrayArray($sQLGeneratorTable->SelectSQL());
		}
		catch(Database_exception $e)
		{
			throw new Database_exception('Wrong SQL for table "' . $this->UniqueName() . '".');
		}

		if(!$resultArrayArray)
			return array();

		foreach($resultArrayArray AS $resultArray)
			$rowArray[] = new PublishedRow($this,
					$resultArray['id'],
					$resultArray['Name']);

		return $rowArray;
	}

	public function SelectUnpublishedRowArray()
	{
		if(!($privilege = $this->SelectPrivilege('select')))
			throw new Database_exception('No privilege for table ' . $this->Id());

		require_once __DIR__ . '/Role.php';

		if(!Role::Select()->SelectRolePrivilege($privilege))
			throw new RolePrivilege_exception($privilege);

		if(!$this->HasUnpublishedColumn())
			throw new Database_exception('No unpublished column.');

		$sQLGeneratorTable = $this->withParentPostgreSQLGeneratorTable();

		require_once __DIR__ . '/../library/Pert/PostgreSQLGenerator/Condition.php';

		require_once __DIR__ . '/../library/Pert/PostgreSQLGenerator/Input.php';

		$sQLGeneratorTable->AddCondition(new \Pert\PostgreSQLGenerator\Condition('Unpublished',
				new \Pert\PostgreSQLGenerator\Input(true)));

		$sQLGeneratorTable->AddCondition(new \Pert\PostgreSQLGenerator\Condition($this->SelectParentTable()->UniqueName(),
				new \Pert\PostgreSQLGenerator\Input($this->Parent()->Id())));

		try
		{
			$resultArrayArray = Database::Get()->SelectResultArrayArray($sQLGeneratorTable->SelectSQL());
		}
		catch(Database_exception $e)
		{
			throw new Database_exception('Wrong SQL for table "' . $this->UniqueName() . '".');
		}

		if(!$resultArrayArray)
			return array();

		foreach($resultArrayArray AS $resultArray)
			$rowArray[] = new UnpublishedRow($this,
					$resultArray['id'],
					$resultArray['Name']);

		return $rowArray;
	}

	public function InsertRow(Array $inputColumnArray)
	{
		if(!($privilege = $this->SelectPrivilege('insert')))
			throw new Database_exception('No ' . $privilage . ' privilege');

		require_once __DIR__ . '/Role.php';

		if(!Role::Select()->SelectRolePrivilege($privilege))
			throw new RolePrivilege_exception($privilege);

		$columnArray = $this->parent->SelectColumnArray();

		if($this->hasNameTable)
			unset($columnArray[1]);

		Database::Get()->UpdateTransactionBegin();

		$id = Database::Get()->SelectResult('SELECT nextval(\'"' . $this->Schema() . '"."' . $this->UniqueName() . '_id"\'::regclass)');

		$query = '
INSERT INTO "' . $this->Schema() . '"."' . $this->backgroundName . '"
("' . $this->SelectParentTable()->UniqueName() . '", id';

		foreach($columnArray AS $column)
		{
			if($column->BackgroundName() == 'Language')
				$this->hasLanguage = false;

			if((($column->ColumnType() == 'dropdown') OR ($column->ColumnType() == 'integer') OR ($column->ColumnType() == 'text') OR ($column->ColumnType() == 'paragraph') OR ($column->ColumnType() == 'string') OR ($column->ColumnType() == 'date') OR ($column->ColumnType() == 'boolean') OR ($column->ColumnType() == 'float')) AND (isset($inputColumnArray[$column->Priority()])))
				$query .= ', "' . $column->BackgroundName() . '"';
		}

		if($this->hasLanguage)
			$query .= ', "Language"';

		$query .= ')
VALUES (' . $this->Parent()->Id() . ', ' . $id;

		foreach($columnArray AS $column)
			if((($column->ColumnType() == 'dropdown') OR ($column->ColumnType() == 'integer') OR ($column->ColumnType() == 'text') OR ($column->ColumnType() == 'paragraph') OR ($column->ColumnType() == 'string') OR ($column->ColumnType() == 'date') OR ($column->ColumnType() == 'boolean') OR ($column->ColumnType() == 'float')) AND (isset($inputColumnArray[$column->Priority()])))
				if($column->ColumnType() == 'dropdown')
					$query .= ', ' . $inputColumnArray[$column->Priority()]->Id();
				elseif(($column->ColumnType() == 'integer') OR ($column->ColumnType() == 'string') OR ($column->ColumnType() == 'text') OR ($column->ColumnType() == 'paragraph') OR ($column->ColumnType() == 'date') OR ($column->ColumnType() == 'boolean') OR ($column->ColumnType() == 'float'))
					$query .= ', ' . Database::Get()->SelectInput($inputColumnArray[$column->Priority()]);

		if($this->hasLanguage)
			$query .= ', ' . Role::Select()->DefaultLanguage()->Id();

		$query .= ')';

		try
		{
			Database::Get()->Update($query);

			if($this->hasNameTable)
			{
				$nameid = Database::Get()->SelectResultArray('SELECT nextval(\'"' . $this->Schema() . '"."' . $this . 'Name_id"\'::regclass)');

				$query = '
	INSERT INTO "' . $this->Schema() . '"."' . $this . '_name"
	("' . $this . '", id, "Language", "Name"';

				if($this->hasNameTableAlternativeColumn)
						$query .= ', "Alternative"';

				$query .= ')
	VALUES (' . $id . ', ' . $nameid . ', ' . Role::Select()->DefaultLanguage()->Id() . ', ' . Database::Get()->SelectInput($inputColumnArray[1]);

				if($this->hasNameTableAlternativeColumn)
						$query .= ', FALSE';

				$query .= ')';

				Database::Get()->Update($query);
			}
		}
		catch(Database_exception $e)
		{
			Database::Get()->UpdateTransactionRollback();

			throw new Database_exception('Wrong SQL for inserting into table "' . $this->UniqueName() . '"');
		}

		Role_Moderator::Select()->InsertChangeLog($privilege,
				$id);

		Database::Get()->UpdateTransactionCommit();

		return $this->SelectRow($id);
	}
}
